<template>
  <div v-loading="loading">
    <el-row :gutter="20" :style="{ width: width, height: height }">
      <el-col :span="12" style="height: 100%;">
        <vue-cropper
          ref="vueCropper"
          :img="options.img"
          :output-size="options.size"
          :output-type="options.outputType"
          :info="options.info"
          :can-scale="options.canScale"
          :auto-crop="options.autoCrop"
          :auto-crop-width="options.autoCropWidth"
          :auto-crop-height="options.autoCropHeight"
          :fixed="options.fixed"
          :fixed-number="options.fixedNumber"
          :full="options.full"
          :fixed-box="options.fixedBox"
          :can-move="options.canMove"
          :can-move-box="options.canMoveBox"
          :original="options.original"
          :center-box="options.centerBox"
          :high="options.high"
          :info-true="options.infoTrue"
          :max-img-size="options.maxImgSize"
          :enlarge="options.enlarge"
          :mode="options.mode"
          @realTime="realTime"
        />
      </el-col>
      <el-col :span="12" class="right_div">
        <el-row type="flex" justify="space-between" style="width: 100%">
          <el-col :span="8">预览</el-col>
          <el-col :span="16" align="right">图片比例：7:3，文件大小：小于1M</el-col>
        </el-row>
        <div class="show_cropper">
          <div :style="previews.div" class="preview">
            <img v-if="previews" :src="previews.url" :style="previews.img">
          </div>
        </div>
        <div>
          <p>链接</p>
          <div><el-input v-model="linkAddressCopy" size="mini" placeholder="请输入" /></div>
        </div>
      </el-col>
    </el-row>
    <el-row :gutter="20" class="gl_pt_10">
      <el-col :span="12">
        <el-button type="primary" plain icon="el-icon-upload2" size="mini" style="position: relative;overflow: hidden;">
          <span>选择图片</span>
          <input type="file" accept="image/png, image/jpeg, image/jpg" class="upload_input" @change="chooseImg">
        </el-button>

        <el-tooltip v-if="photograph" class="item" effect="dark" placement="top">
          <div slot="content">拍照</div>
          <el-button size="mini" icon="el-icon-camera-solid" @click="getCompetence()" />
        </el-tooltip>

        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">放大</div>
          <el-button plain icon="el-icon-plus" size="mini" @click="changeScale(1)" />
        </el-tooltip>
        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">缩小</div>
          <el-button plain icon="el-icon-minus" size="mini" @click="changeScale(-1)" />
        </el-tooltip>
        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">逆时针</div>
          <el-button plain icon="el-icon-refresh-left" size="mini" @click="rotateLeft()" />
        </el-tooltip>
        <el-tooltip class="item" effect="dark" placement="top">
          <div slot="content">顺时针</div>
          <el-button plain icon="el-icon-refresh-right" size="mini" @click="rotateRight()" />
        </el-tooltip>
      </el-col>
      <el-col align="center" class="gl_pt_10">

        <el-dialog
          :modal="false"
          title="拍摄照片"
          class="gl_dialog_TitleLine gl_dl_footer"
          :visible.sync="dialogVisible"
          :close-on-click-modal="false"
          :append-to-body="true"
          width="532px"
          top="25vh"
        >
          <video id="videoCamera" width="500" height="300" autoplay />
          <canvas id="canvasCamera" style="display:none;" width="300" height="300" />
          <span slot="footer" class="dialog-footer">
            <el-button @click="stopNavigator()">关闭摄像头</el-button>
            <el-button @click="setImage()">拍照</el-button>
          </span>
        </el-dialog>

        <el-button type="default" size="mini" @click="goBack()">取消</el-button>
        <el-button type="primary" size="mini" @click="submitImg()">保存</el-button>
      </el-col>
    </el-row>
  </div>
</template>
<script>
import axios from 'axios';
import { getToken } from '@/lib/auth';
export default {
  name: 'PhotoCropper',
  props: {
    // 上传地址 - 完整的地址
    action: {
      type: String,
      required: true
    },
    // 链接
    linkAddress: {
      type: String,
      required: true
    },
    // 裁剪配置参数 具体参数配置详见 https://github.com/xyxiao001/vue-cropper
    option: {
      type: Object,
      required: true
    },
    // 裁剪容器宽度
    width: {
      type: String,
      required: false,
      default: '100%'
    },
    // 裁剪容器高度
    height: {
      type: String,
      required: false,
      default: '375px'
    },
    // 是否开启拍照
    photograph: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  data() {
    return {
      dialogVisible: false,
      loading: false,
      thisCancas: null,
      thisContext: null,
      thisVideo: null,
      imgSrc: '', // 图片拍照
      linkAddressCopy: '', // 链接
      options: {
        img: '', // 裁剪图片的地址
        outputSize: 1, // 裁剪生成图片的质量
        outputType: 'png', // 裁剪生成图片的格式
        info: true, // 裁剪框的大小信息
        canScale: true, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        autoCropWidth: '200px', // 默认生成截图框宽度
        autoCropHeight: '200px', // 默认生成截图框高度
        fixed: true, // 是否开启截图框宽高固定比例
        fixedNumber: [1, 1], // 截图框的宽高比例
        full: false, // 是否输出原图比例的截图
        fixedBox: true, // 固定截图框大小 不允许改变
        canMove: true, // 上传图片是否可以移动
        canMoveBox: true, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: false, // 截图框是否被限制在图片里面
        high: true, // 是否按照设备的dpr 输出等比例图片
        infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        maxImgSize: 4000, // 限制图片最大宽度和高度
        enlarge: 1, // 图片根据截图框输出比例倍数
        mode: '100% auto' // 图片默认渲染方式
      },
      tokenInfo: getToken(),
      // 预览
      previews: '',
      formatFile: '.jpg,.png,.jpeg'
    };
  },
  watch: {
    option: {
      handler() {
        this.init();
        this.initOption();
      },
      immediate: true,
      deep: true
    }
  },
  created() {
    // this.init();
    this.initOption();
  },
  methods: {
    init() {
      this.loading = false;
      this.file = null;
      this.options.img = '';
      this.cropperImg = null;
      console.log('option', this.option);
    },
    initOption() {
      console.log('option', this.option);
      for (const i in this.option) {
        if (i in this.options) {
          this.$set(this.options, i, this.option[i]);
        }
      }
      this.linkAddressCopy = this.linkAddress;
    },
    // 选择图片
    chooseImg(e) {
      const file = e.target.files[0];
      var _imgType = file.name.split('.');
      _imgType = _imgType[_imgType.length - 1];
      _imgType = _imgType && _imgType.toLowerCase();
      console.log(this.formatFile);
      if (this.formatFile.indexOf(_imgType) === -1) {
        this.handleFormatError(file);
        return false;
      }
      console.log(file);
      const fileReader = new FileReader();
      fileReader.readAsDataURL(file);
      this.file = file;
      fileReader.onloadend = () => {
        this.options.img = fileReader.result;
        console.log(this.options.img);
      };
      e.target.value = '';
    },
    handleFormatError(file) {
      this.$message({
        type: 'error',
        showClose: true,
        message: `文件[${file.name}]格式不正确，请上传 ${this.formatFile}格式的文件。`
      });
    },
    // 缩放
    changeScale(num) {
      num = num || 1;
      this.$refs.vueCropper.changeScale(num);
    },
    // 坐旋转
    rotateLeft() {
      this.$refs.vueCropper.rotateLeft();
    },
    // 右旋转
    rotateRight() {
      this.$refs.vueCropper.rotateRight();
    },
    // 保存
    submitImg() {
      this.$refs.vueCropper.getCropBlob(data => {
        const _type = data.type && data.type.split('/')[1];
        const _name = this.file && this.file.name || (Math.floor(Math.random() * 100000) + `.${_type}`);
        const file = new window.File([data], _name, { type: data.type });
        this.cropperImg = file;
        this.$emit('photoCropperSave', this.cropperImg, this.linkAddressCopy);
      });
    },
    goBack() {
      this.$emit('goBack');
    },
    // 图片上传
    upload() {
      return new Promise((resolve, reject) => {
        if (!this.cropperImg) reject(new Error());
        const form = new FormData();
        form.append('formFile', this.cropperImg);
        this.loading = true;
        this.uploadApi(this.action, form).then(res => {
          if (res.status === 200) {
            resolve(res.data);
            this.loading = false;
          } else {
            reject(res.data);
            this.loading = false;
          }
        });
      });
    },
    uploadApi(url, file) {
      const config = {
        headers: {
          Authorization: 'Bearer ' + this.tokenInfo
        }
      };
      return axios.post(url, file, config);
    },
    // 预览
    realTime(data) {
      this.previews = data;
    },
    // 打开摄像头
    getCompetence() {
      this.dialogVisible = true;
      var _this = this;
      this.$nextTick(function() {
        this.thisCancas = document.getElementById('canvasCamera');
        this.thisContext = this.thisCancas.getContext('2d');
        this.thisVideo = document.getElementById('videoCamera');

        if (navigator.mediaDevices === undefined) {
          navigator.mediaDevices = {};
        }
        if (navigator.mediaDevices.getUserMedia === undefined) {
          navigator.mediaDevices.getUserMedia = function (constraints) {
          // 首先获取现存的getUserMedia(如果存在)
            var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;
            // 有些浏览器不支持，会返回错误信息
            // 保持接口一致
            if (!getUserMedia) {
              return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
            }
            // 否则，使用Promise将调用包装到旧的navigator.getUserMedia
            return new Promise(function (resolve, reject) {
              getUserMedia.call(navigator, constraints, resolve, reject);
            });
          };
        }
        var constraints = { audio: false, video: { width: 300, height: 300, transform: 'scaleX(-1)' }};
        navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
        // 旧的浏览器可能没有srcObject
          if ('srcObject' in _this.thisVideo) {
            _this.thisVideo.srcObject = stream;
          } else {
          // 避免在新的浏览器中使用它，因为它正在被弃用。
            _this.thisVideo.src = window.URL.createObjectURL(stream);
          }
          _this.thisVideo.onloadedmetadata = function (e) {
            _this.thisVideo.play();
          };
        }).catch(err => {
          console.log(err);
        });
      });
    },
    //  绘制图片（拍照功能）
    setImage () {
      var _this = this;
      // 点击，canvas画图
      _this.thisContext.drawImage(_this.thisVideo, 0, 0, 300, 300);
      // 获取图片base64链接
      var image = this.thisCancas.toDataURL('image/png');
      _this.imgSrc = image;
      _this.options.img = _this.imgSrc;
    },
    // base64转文件
    dataURLtoFile (dataurl, filename) {
      var arr = dataurl.split(',');
      var mime = arr[0].match(/:(.*?);/)[1];
      var bstr = atob(arr[1]);
      var n = bstr.length;
      var u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, { type: mime });
    },
    // 关闭摄像头
    stopNavigator () {
      this.dialogVisible = false;
      this.thisVideo.srcObject.getTracks()[0].stop();
    }
  }
};
</script>
<style lang="scss" scoped>
.upload_input {
  position: absolute;
  top: 0;
  left: -100px;
  opacity: 0;
  width: calc(100% + 100px);
  height: 100%;
  cursor: pointer;
  overflow: hidden;
}
.right_div {
  height: 100%;
}
.show_cropper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 75%;
  border: 1px solid #ddd;
  margin: 15px 0;
  border-radius: 10px;
}
.preview {
  border: 1px solid #ddd;
  overflow: hidden;
}
</style>
